// 4.写一个简单的myString类，实现你能实现的所有功能。一些功能用函数代替。

#include <iostream>
#include <cstring> // 用于 strlen, strcpy, strcmp 等
#include <stdexcept> // 用于异常处理

class MyString {
private:
    char* m_data; // 存储字符串数据
    size_t m_length; // 字符串长度

    // 辅助函数：分配内存并复制字符串
    void allocateAndCopy(const char* str) {
        m_length = strlen(str);
        m_data = new char[m_length + 1]; // +1 用于 null 终止符
        strcpy(m_data, str);
    }

public:
    // 1. 构造函数
    MyString() : m_data(new char[1]), m_length(0) {
        m_data[0] = '\0';
    }

    MyString(const char* str) {
        if (str == nullptr) {
            m_data = new char[1];
            m_data[0] = '\0';
            m_length = 0;
        } else {
            allocateAndCopy(str);
        }
    }

    // 2. 拷贝构造函数
    MyString(const MyString& other) {
        allocateAndCopy(other.m_data);
    }

    // 3. 析构函数
    ~MyString() {
        delete[] m_data;
    }

    // 4. 赋值运算符
    MyString& operator=(const MyString& other) {
        if (this != &other) { // 防止自赋值
            delete[] m_data;
            allocateAndCopy(other.m_data);
        }
        return *this;
    }

    // 5. 获取长度
    size_t length() const {
        return m_length;
    }

    // 6. 获取C风格字符串
    const char* c_str() const {
        return m_data;
    }

    // 7. 字符串连接
    MyString operator+(const MyString& other) const {
        MyString newStr;
        delete[] newStr.m_data; // 释放默认构造的空字符串
        
        newStr.m_length = m_length + other.m_length;
        newStr.m_data = new char[newStr.m_length + 1];
        
        strcpy(newStr.m_data, m_data);
        strcat(newStr.m_data, other.m_data);
        
        return newStr;
    }

    // 8. 字符串比较
    bool operator==(const MyString& other) const {
        return strcmp(m_data, other.m_data) == 0;
    }
    
    bool operator!=(const MyString& other) const {
        return !(*this == other);
    }
    
    bool operator<(const MyString& other) const {
        return strcmp(m_data, other.m_data) < 0;
    }
    
    bool operator>(const MyString& other) const {
        return strcmp(m_data, other.m_data) > 0;
    }

    // 9. 下标访问
    char& operator[](size_t index) {
        if (index >= m_length) {
            throw std::out_of_range("Index out of range");
        }
        return m_data[index];
    }
    
    const char& operator[](size_t index) const {
        if (index >= m_length) {
            throw std::out_of_range("Index out of range");
        }
        return m_data[index];
    }

    // 10. 查找子串
    size_t find(const MyString& substr) const {
        const char* result = strstr(m_data, substr.m_data);
        if (result == nullptr) {
            return std::string::npos; // 通常定义为 (size_t)-1
        }
        return result - m_data;
    }

    // 11. 子串
    MyString substr(size_t pos, size_t len = std::string::npos) const {
        if (pos >= m_length) {
            throw std::out_of_range("Position out of range");
        }
        
        size_t actualLen = len;
        if (len == std::string::npos || pos + len > m_length) {
            actualLen = m_length - pos;
        }
        
        MyString newStr;
        delete[] newStr.m_data;
        
        newStr.m_length = actualLen;
        newStr.m_data = new char[actualLen + 1];
        
        strncpy(newStr.m_data, m_data + pos, actualLen);
        newStr.m_data[actualLen] = '\0';
        
        return newStr;
    }

    // 12. 清空字符串
    void clear() {
        delete[] m_data;
        m_data = new char[1];
        m_data[0] = '\0';
        m_length = 0;
    }

    // 13. 判断是否为空
    bool empty() const {
        return m_length == 0;
    }

    // 14. 输出流操作符
    friend std::ostream& operator<<(std::ostream& os, const MyString& str) {
        os << str.m_data;
        return os;
    }

    // 15. 输入流操作符
    friend std::istream& operator>>(std::istream& is, MyString& str) {
        char buffer[1024]; // 临时缓冲区
        is >> buffer;
        str = MyString(buffer);
        return is;
    }
};

// 测试代码
int main() {
    // 测试构造函数
    MyString s1;
    MyString s2("Hello");
    MyString s3 = s2; // 拷贝构造
    
    std::cout << "s1: " << s1 << " (length: " << s1.length() << ")" << std::endl;
    std::cout << "s2: " << s2 << " (length: " << s2.length() << ")" << std::endl;
    std::cout << "s3: " << s3 << " (length: " << s3.length() << ")" << std::endl;
    
    // 测试赋值运算符
    MyString s4;
    s4 = s2;
    std::cout << "s4: " << s4 << std::endl;
    
    // 测试字符串连接
    MyString s5 = s2 + " World";
    std::cout << "s5: " << s5 << std::endl;
    
    // 测试比较运算符
    std::cout << "s2 == s3: " << (s2 == s3) << std::endl;
    std::cout << "s2 != s5: " << (s2 != s5) << std::endl;
    
    // 测试下标访问
    std::cout << "s5[0]: " << s5[0] << std::endl;
    s5[0] = 'h';
    std::cout << "After modification, s5: " << s5 << std::endl;
    
    // 测试查找
    MyString s6("ll");
    std::cout << "Position of 'll' in s5: " << s5.find(s6) << std::endl;
    
    // 测试子串
    MyString s7 = s5.substr(2, 3);
    std::cout << "Substring of s5 (2,3): " << s7 << std::endl;
    
    // 测试清空
    s5.clear();
    std::cout << "After clear, s5: " << s5 << " (empty: " << s5.empty() << ")" << std::endl;
    
    // 测试输入
    MyString s8;
    std::cout << "Enter a string: ";
    std::cin >> s8;
    std::cout << "You entered: " << s8 << std::endl;
    
    return 0;
}